﻿using LightCAD.Core.Elements;
using LightCAD.Core;
using LightCAD.Runtime;
using SkiaSharp;
using System;
using System.Collections.Generic;
using System.Linq;
using LightCAD.MathLib;
using System.IO;

namespace LightCAD.Drawing.Actions
{
    public class MTextAction : ElementAction
    {
        public static string CommandName;
        public static LcCreateMethod[] CreateMethods;

        public MTextAction() { }
        public MTextAction(IDocumentEditor docEditor) : base(docEditor)
        {
            this.commandCtrl.WriteInfo("命令 ：MTEXT");
        }

        static MTextAction()
        {
            CommandName = "MTEXT";
            CreateMethods = new LcCreateMethod[1];
            CreateMethods[0] = new LcCreateMethod()
            {
                Name = "MTEXT",
                Description = "MTEXT",
                Steps = new LcCreateStep[]
                {
                    new LcCreateStep{ Name="Step0", Options="指定第一个角点：" },
                    new LcCreateStep{ Name="Step1", Options="指定对角点：" },
                    new LcCreateStep{ Name="Step2", Options="输入字体：" },
                    new LcCreateStep{ Name="Step3", Options="输入文字：" },
                }
            };

        }
        internal static void Initilize()
        {
            ElementActions.MText = new MTextAction();
            LcDocument.ElementActions.Add(BuiltinElementType.MText, ElementActions.MText);
        }

        private Vector2 point { get; set; }

        private PointInputer inputer { get; set; }
      
        private Vector2 firstPoint;
        private Vector2 endPoint;
        private Box2 box2;
        private string TextVale;
        private string Typeface;
        private bool IsLinefeed = false;


        public async void ExecCreate(string[] args = null)
        {
            this.StartCreating();
            //this.Segments = new List<RolineSegment>();
            var curMethod = CreateMethods[0];
            var ElementInputer = new ElementInputer(this.docEditor);
            this.inputer = new PointInputer(this.docEditor);
            Step0:
            var step0 = curMethod.Steps[0];
            var result0 = await inputer.Execute(step0.Options);
            if (inputer.isCancelled) { this.Cancel(); return; }
            // zcb: 增加Res0为空的判定
            if (result0 == null)
            {
                this.Cancel();
                goto End;
            }
            if (result0.ValueX == null)
            {
                goto Step0;
            }
            else
            {
                this.firstPoint = (Vector2)result0.ValueX;
                goto Step1;
            }
            Step1:
            var step1 = curMethod.Steps[1];
            var result1 = await inputer.Execute(step1.Options);
            if (inputer.isCancelled) { this.Cancel(); return; }
            // zcb: 增加Res0为空的判定
            if (result1 == null)
            {
                this.Cancel();
                goto End;
            }
            if (result1.ValueX == null)
            {
                if (result1.Option != null)
                {
                }
                else
                {
                    goto End;
                }
            }
            else
            {
                this.endPoint = (Vector2)result1.ValueX;
                this.box2= new Box2().SetFromPoints((Vector2)result0.ValueX, (Vector2)result1.ValueX);
                goto Step2;
            }
            Step2:
            var step2 = curMethod.Steps[2];
            var result2 = await inputer.Execute(step2.Options);
            if (inputer.isCancelled) { this.Cancel(); return; }
            // zcb: 增加Res0为空的判定
            if (result2 == null)
            {
                this.Cancel();
                goto End;
            }
            if (result2.ValueX == null)
            {
                if (result2.Option != null)
                {
                    if (result2.Option != "")
                    {
                        //判断输入的字体是否存在
                        var index = SKFontManager.Default.FontFamilies.ToList().IndexOf(result2.Option);
                        if (index == -1)
                        {
                            goto Step2;
                        }
                        else {
                            this.Typeface = result2.Option;
                        }

                    }
                    goto Step3;
                }
                else
                {
                    goto Step3;
                }
            }
            else
            {
                goto Step3;
            }
            Step3:
            var step3 = curMethod.Steps[3];
            var result3 = await inputer.Execute(step3.Options);
            if (inputer.isCancelled) { this.Cancel(); return; }
            // zcb: 增加Res0为空的判定
            if (result3 == null)
            {
                this.Cancel();
                goto End;
            }
            if (result3.ValueX == null)
            {
                if (result3.Option != null)
                {
                    if (result3.Option != "")
                    {
                        this.TextVale = result3.Option;
                        CreatMText();

                    }
                    goto End;
                }
                else
                {
                    goto Step3;
                }
            }
            else
            {
                goto Step3;
            }
            End:
            this.EndCreating();
        }
            //        using SkiaSharp;

            //// 读取TTF文件
            //SKTypeface typeface = SKTypeface.FromFile("path/to/font.ttf");

            //// 使用typeface进行绘制
            //using (SKPaint paint = new SKPaint())
            //{
            //    paint.Typeface = typeface;
            //    paint.TextSize = 24;

            //    using (SKSurface surface = SKSurface.Create(new SKImageInfo(400, 200)))
            //    {
            //        SKCanvas canvas = surface.Canvas;
            //    canvas.Clear(SKColors.White);

            //        canvas.DrawText("Hello, SkiaSharp!", 50, 100, paint);

            //        SKImage image = surface.Snapshot();
            //    image.Encode(SKEncodedImageFormat.Png).SaveTo("output.png");
            //}
            //            using SkiaSharp;

            //// 读取SHX文件
            //SKTypeface typeface = SKTypeface.FromTypefaceStream(new MemoryStream(File.ReadAllBytes("path/to/font.shx")));

    //}
    public void CreateOutLine(IFrameDefWindow win)
        {
            //Box2d box2D = (Box2d)win.Box;

            //selectedElements.Add(this.docRt.Document.ModelSpace.AddLine(box2D.LeftTop, box2D.RightTop));
            //selectedElements.Add(this.docRt.Document.ModelSpace.AddLine(box2D.RightTop, box2D.RightBottom));
            //selectedElements.Add(this.docRt.Document.ModelSpace.AddLine(box2D.RightBottom, box2D.LeftBottom));
            //selectedElements.Add(this.docRt.Document.ModelSpace.AddLine(box2D.LeftBottom, box2D.LeftTop));
            ////增加内框名
            //var nameFrameLeftTop = box2D.LeftTop + new Vector2d(0, 600);
            //var nameFrameLeftBottom = box2D.LeftTop;

            //var nameFrameRightTop = nameFrameLeftTop + new Vector2d(Math.Abs(box2D.RightTop.X - box2D.LeftTop.X) / 2, 0);
            //var nameFrameRightBottom = nameFrameLeftBottom + new Vector2d(Math.Abs(box2D.RightTop.X - box2D.LeftTop.X) / 2, 0);
            //selectedElements.Add(this.docRt.Document.ModelSpace.AddLine(nameFrameLeftTop, nameFrameRightTop));
            //selectedElements.Add(this.docRt.Document.ModelSpace.AddLine(nameFrameRightTop, nameFrameRightBottom));
            //selectedElements.Add(this.docRt.Document.ModelSpace.AddLine(nameFrameRightBottom, nameFrameLeftBottom));
            //selectedElements.Add(this.docRt.Document.ModelSpace.AddLine(nameFrameLeftBottom, nameFrameLeftTop));
            //selectedElements.Add(this.docRt.Document.ModelSpace.AddLine(nameFrameLeftBottom, nameFrameLeftTop));
            
        }
        public void CreatMText()
        {
            var doc = this.docRt.Document;
            DocumentManager.CurrentRecorder.BeginAction("MText");
            var MText = doc.CreateObject<LcMText>();
            MText.Firstpoint = this.firstPoint;
            MText.Endpoint = this.endPoint;
            MText.Box2D = this.box2;
            MText.Mtext = this.TextVale;
            MText.Typeface = this.Typeface;
            doc.ModelSpace.InsertElement(MText);
            this.docRt.Action.ClearSelects();
            DocumentManager.CurrentRecorder.EndAction();
        }

        public override void CreateElement(LcElement element, Matrix3 matrix)
        {
        
        }
        public override void CreateElement(LcElement element, Vector2 basePoint, double scaleFactor)
        {
           
        }
        public override void CreateElement(LcElement element, Vector2 basePoint, Vector2 scaleVector)
        {
           
        }

        public override void Draw(SKCanvas canvas, LcElement element, Matrix3 matrix)
        {
            var MText = element as LcMText;

            //取出矩形框的开始点 结束点

            var mstart = matrix.MultiplyPoint(MText.Firstpoint);
            var mend = matrix.MultiplyPoint(MText.Endpoint);
            var mtext = MText.Mtext;
            var start = this.vportRt.ConvertWcsToScr(mstart).ToSKPoint();
            var end = this.vportRt.ConvertWcsToScr(mend).ToSKPoint();
            var typeface = MText.Typeface;


            //var box2d = MText.box2D;
            var box2d= MText.Box2D;
            //文字初始点
          
            var wzlocation = this.vportRt.ConvertWcsToScr(matrix.MultiplyPoint(box2d.LeftTop)).ToSKPoint();
            //矩形宽高
            var RectWidth = Math.Abs(start.X - end.X);
            var RectHeight = Math.Abs(start.Y - end.Y);



            var pen = this.GetDrawPen(MText);

          

            if (pen == Runtime.Constants.defaultPen)
            {
                using (var elePen = new SKPaint { Color = new SKColor(element.GetColorValue()), IsStroke = true })
                {
                    using (var paint = new SKPaint())
                    {
                        //得到文字长度
                        var tRect = new SKRect();
                        //文字长度
                        var tWidth = paint.MeasureText(mtext, ref tRect);



                        var fontManager = SKFontManager.Default;
                        var emojiTypeface = fontManager.MatchCharacter('时');
                        paint.TextSize = (float)(this.vportRt.Viewport.Scale*400);
                        //paint.TextAlign = SKTextAlign.Center;
                        //抗锯齿
                        paint.IsAntialias = false;
                        paint.Color = new SKColor(0x42, 0x81, 0xA4);
                        paint.IsStroke = false;
                        paint.Typeface = emojiTypeface;

                        //var skpath = new SKPath();
                        //skpath.MoveTo(start);
                        ////skpath.LineTo((float)start.X, (float)start.Y);
                        //skpath.LineTo((float)newend.X, (float)newend.Y);
                        //canvas.DrawTextOnPath(mtext, skpath, 0, 0, paint);




                        SKFont sKFont = new SKFont();
                        // 获取宋体在字体集合中的下标
                        var index = SKFontManager.Default.FontFamilies.ToList().IndexOf(typeface);
                        // 创建宋体字形
                        var songtiTypeface = SKFontManager.Default.GetFontStyles(index).CreateTypeface(0);
                        sKFont.Typeface = songtiTypeface;
                        sKFont.Size= (float)(this.vportRt.Viewport.Scale * 400);
                        //sKFont.Typeface = SKFontManager.Default.GetFontStyles("黑体").CreateTypeface(0);
                        //sKFont.Size = (float)15;

                        //// 获取宋体在字体集合中的下标
                        //var index = SKFontManager.Default.FontFamilies.ToList().IndexOf("宋体");
                        //// 创建宋体字形
                        //var songtiTypeface = SKFontManager.Default.GetFontStyles(index).CreateTypeface(0);

                        //计算矩形宽度与文字宽度 算出需要写几行

                        DrawMuiltLineText(canvas, mtext,(float)wzlocation.X, (float)wzlocation.Y, paint, sKFont, (float)RectWidth, 10000);

                        //canvas.DrawText(mtext,start.X,start.Y,sKFont,paint);


                    }


                }
            }
            else
            {
                using (var paint = new SKPaint())
                {
                    var fontManager = SKFontManager.Default;
                    var emojiTypeface = fontManager.MatchCharacter('时');
                    paint.TextSize = (float)(this.vportRt.Viewport.Scale*400);
                    //paint.TextAlign = SKTextAlign.Center;
                    paint.IsAntialias = false;
                    paint.Color = new SKColor(0x42, 0x81, 0xA4);
                    paint.IsStroke = false;
                    paint.Typeface = emojiTypeface;




                    SKFont sKFont = new SKFont();
                    // 获取宋体在字体集合中的下标
                    var index = SKFontManager.Default.FontFamilies.ToList().IndexOf(typeface);
                    // 创建宋体字形
                    var songtiTypeface = SKFontManager.Default.GetFontStyles(index).CreateTypeface(0);
                    sKFont.Typeface = songtiTypeface;
                    sKFont.Size = (float)(this.vportRt.Viewport.Scale * 400);

                    DrawMuiltLineText(canvas, mtext, wzlocation.X, wzlocation.Y, paint, sKFont, (float)RectWidth, 10);

                    //canvas.DrawText(mtext, start.X, start.Y, sKFont, paint);
                }
            }

        }

        public override ControlGrip[] GetControlGrips(LcElement element)
        {
            var dim = element as LcMText;

            var grips = new List<ControlGrip>();
            var gripStartr = new ControlGrip
            {
                //文字点  需要给两个  （起点 和中间点）
                Element = dim,
                Name = "Start",
                Position = dim.Firstpoint
            };
            grips.Add(gripStartr);
            var gripRightTop = new ControlGrip
            {
                Element = dim,
                Name = "RightTop",
                Position = dim.Box2D.RightTop
            };
            grips.Add(gripRightTop);
            var gripBottomCenter = new ControlGrip
            {
                Element = dim,
                Name = "BottomCenter",
                Position = new Vector2(dim.Box2D.LeftBottom.X+(Math.Abs(dim.Box2D.RightBottom.X-dim.Box2D.LeftBottom.X)/2), dim.Box2D.LeftBottom.Y)
            };
            grips.Add(gripBottomCenter);


            return grips.ToArray();
        }
        private string _gripName;

        private Vector2 _position;
        private LcMText _MText;


        public static double distance(Vector2 p1, Vector2 p2)
        {
            double result = 0;
            result = Math.Sqrt((p1.X - p2.X) * (p1.X - p2.X) + (p1.Y - p2.Y) * (p1.Y - p2.Y));
            return result;

        }
        public override void SetDragGrip(LcElement element, string gripName, Vector2 position, bool isEnd)
        {
            var MText = element as  LcMText;

            _MText = MText;
            if (!isEnd)
            {
                _gripName = gripName;
                _position = position;
            }
            else
            {
                //文字点
                if (gripName == "Start") {
                    //得到移动向量
                     var xl  = new Vector2(_position.X - _MText.Firstpoint.X, _position.Y - _MText.Firstpoint.Y);
                    //得到移动的距离
                    double dis = Math.Abs(distance(_MText.Firstpoint, _position));
                    //得到新的结束点
                    Vector2 newend = _MText.Endpoint + (new Vector2(xl.X * dis, xl.Y * dis)) / Math.Sqrt(Math.Abs((Math.Pow(xl.X, 2.0) + Math.Pow(xl.Y, 2.0))));

                    _MText.Set(start: _position, end: newend);

                }
                //矩形框的拉伸点
                if (gripName == "RightTop")
                {
                    //得到新的结束点
                    var newbtm = new Vector2(_position.X, _MText.Box2D.RightBottom.Y);
                    var box2 = new Box2().SetFromPoints(_MText.Box2D.LeftTop, newbtm);
                    _MText.Set(end: newbtm);
                    
                }
                if (gripName == "BottomCenter")
                {
                    //得到新的结束点
                    var newbtm = new Vector2(_MText.Box2D.RightBottom.X, _position.Y);
                    var box2 = new Box2().SetFromPoints(_MText.Box2D.LeftTop, newbtm);
                    _MText.Set(end: newbtm);
                    
                }

            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="canvas"></param>
        public override void DrawDragGrip(SKCanvas canvas)
        {
            if (_MText == null) return;
            var box = _MText.Box2D;
            Vector2 anglePoint1 = box.LeftTop;
            Vector2 anglePoint2 = box.RightTop;
            Vector2 anglePoint3 = box.RightBottom;
            Vector2 anglePoint4 = box.LeftBottom;

            //矩形框下边中点
          var BottomCenter=  new Vector2(box.LeftBottom.X + (Math.Abs(box.RightBottom.X - box.LeftBottom.X) / 2), box.LeftBottom.Y);

            var SKPoint1 = this.vportRt.ConvertWcsToScr(anglePoint1).ToSKPoint();
            var SKPoint2 = this.vportRt.ConvertWcsToScr(anglePoint2).ToSKPoint();
            var SKPoint3 = this.vportRt.ConvertWcsToScr(anglePoint3).ToSKPoint();
            var SKPoint4 = this.vportRt.ConvertWcsToScr(anglePoint4).ToSKPoint();
            var SKBtocenter = this.vportRt.ConvertWcsToScr(BottomCenter).ToSKPoint();
             
            var position= this.vportRt.ConvertWcsToScr(_position).ToSKPoint();

            if (_gripName== "Start") {
                //移动的是文字点
                canvas.DrawLine(SKPoint1, position, Constants.draggingPen);

            }
            if (_gripName == "RightTop") {
                //移动矩形框右边点
                //鼠标移动辅助线
                canvas.DrawLine(SKPoint2, position, Constants.draggingPen);
                //新的右边两个点（只变动X值）
                var newtop = this.vportRt.ConvertWcsToScr(new Vector2(_position.X, anglePoint2.Y)).ToSKPoint();
                var newbtm = this.vportRt.ConvertWcsToScr(new Vector2(_position.X, anglePoint3.Y)).ToSKPoint();

                canvas.DrawLine(SKPoint1, newtop, Constants.draggingPen);
                canvas.DrawLine(SKPoint4, newbtm, Constants.draggingPen);
                canvas.DrawLine(newtop, newbtm, Constants.draggingPen);
                canvas.DrawLine(SKPoint4, SKPoint1, Constants.draggingPen);


            }
            if (_gripName == "BottomCenter")
            {
                //移动矩形框下边点
                //鼠标移动辅助线
                canvas.DrawLine(SKBtocenter, position, Constants.draggingPen);
                //新的下边两个点（只变动Y值）
                var newLbtm = this.vportRt.ConvertWcsToScr(new Vector2(anglePoint4.X, _position.Y)).ToSKPoint();
                var newRbtm = this.vportRt.ConvertWcsToScr(new Vector2(anglePoint3.X, _position.Y)).ToSKPoint();
                canvas.DrawLine(SKPoint1, newLbtm, Constants.draggingPen);
                canvas.DrawLine(SKPoint2, newRbtm, Constants.draggingPen);
                canvas.DrawLine(newLbtm, newRbtm, Constants.draggingPen);
                canvas.DrawLine(SKPoint1, SKPoint2, Constants.draggingPen);

            }


            ////辅助元素的颜色 
            //canvas.DrawLine(SKPoint1, SKPoint2, Constants.draggingPen);
            //canvas.DrawLine(SKPoint2, SKPoint3, Constants.draggingPen);
            //canvas.DrawLine(SKPoint3, SKPoint4, Constants.draggingPen);
            //canvas.DrawLine(SKPoint4, SKPoint1, Constants.draggingPen);
        }
        public override void DrawAuxLines(SKCanvas canvas)
        {
            if (firstPoint == null) return;
            if (endPoint != null) return;
            var mp = this.vportRt.PointerMovedPosition.ToVector2d();
            var wcs_mp = this.vportRt.ConvertScrToWcs(mp);

            Vector2 anglePoint1 = (Vector2)firstPoint;
            Vector2 anglePoint3 = wcs_mp;
            Vector2 anglePoint2 = new Vector2(anglePoint1.X, anglePoint3.Y);
            Vector2 anglePoint4 = new Vector2(anglePoint3.X, anglePoint1.Y);

            var SKPoint1 = this.vportRt.ConvertWcsToScr(anglePoint1).ToSKPoint();
            var SKPoint2 = this.vportRt.ConvertWcsToScr(anglePoint2).ToSKPoint();
            var SKPoint3 = this.vportRt.ConvertWcsToScr(anglePoint3).ToSKPoint();
            var SKPoint4 = this.vportRt.ConvertWcsToScr(anglePoint4).ToSKPoint();
            //辅助元素的颜色 
            canvas.DrawLine(SKPoint1, SKPoint2, new SKPaint { Color = this.vportRt.GetAuxColorValue(), IsStroke = true });
            canvas.DrawLine(SKPoint2, SKPoint3, new SKPaint { Color = this.vportRt.GetAuxColorValue(), IsStroke = true });
            canvas.DrawLine(SKPoint3, SKPoint4, new SKPaint { Color = this.vportRt.GetAuxColorValue(), IsStroke = true });
            canvas.DrawLine(SKPoint4, SKPoint1, Constants.auxElementPen);
        }

        /// </summary>
        /// <param name="canvas">画布</param>
        /// <param name="text">多行文字</param>
        /// <param name="x">x坐标</param>
        /// <param name="y">y坐标</param>
        /// <param name="paint">画笔</param>
        /// <param name="maxWidth">单行文字最大宽度</param>
        /// <param name="maxLines">最大行数，如果超出，则使用...</param>
        public  void DrawMuiltLineText(SKCanvas canvas, string text, float x, float y, SKPaint paint,SKFont font, float maxWidth, int maxLines)
        {

            //判断文字中是否后换行特殊字符（/*）

            var textlist = text.Split("/*");
            if (textlist.Length > 1)
            {
                //表示按文字来换行
                for (int i = 0; i < textlist.Length; i++)
                {
                    //文字矩形
                    var tRect = new SKRect();
                    //计算文字矩形
                    paint.MeasureText(textlist[i], ref tRect);
                    //计算坐标
                    var tPoint = new SKPoint
                    {
                        X = x - tRect.Left,
                        //这里注意Y坐标需要加上行高
                        Y = y + i * paint.FontSpacing - tRect.Top
                    };
                    //写出一行文字
                    canvas.DrawText(textlist[i], tPoint.X, tPoint.Y, font, paint);

                }



            }
            else 
            {
                //表示按矩形来分割
                //已写出行数
                int lines = 0;
                //省略号宽度
                //var ellipseWidth = paint.MeasureText("...");
                //如果文字没写完且已写行数小于最大行数，则继续写出
                //while (!string.IsNullOrEmpty(text) && lines < maxLines)
                while (!string.IsNullOrEmpty(text))
                {
                    //单行文字
                    string lineStr;
                    //单行文字长度
                    long strLength;
                    ////非最后一行  
                    //if (lines != maxLines - 1)
                    //{
                    //调用BreakText方法，可计算指定宽度能写出多少文字
                    strLength = paint.BreakText(text, maxWidth, out float ww, out lineStr);
                    //}
                    ////最后一行
                    //else
                    //{
                    //    //调用BreakText方法计算单行文字长度，这里需减去省略号宽度
                    //    strLength = paint.BreakText(text, maxWidth - ellipseWidth, out float ww, out lineStr);
                    //    //假如字还没写完，需加省略号
                    //    if (strLength < text.Length)
                    //    {
                    //        lineStr += "...";
                    //    }
                    //}
                    //文字矩形
                    var tRect = new SKRect();
                    //计算文字矩形
                    paint.MeasureText(lineStr, ref tRect);
                    //计算坐标
                    var tPoint = new SKPoint
                    {
                        X = x - tRect.Left,
                        //这里注意Y坐标需要加上行高
                        Y = y + lines * paint.FontSpacing - tRect.Top
                    };
                    //写出一行文字
                    canvas.DrawText(lineStr, tPoint.X, tPoint.Y, font, paint);
                    //已写出行数加1
                    lines++;
                    //取剩余文字
                    text = text.Substring((int)strLength);


                }


           
            }
        }

    }
}
